// DevotionalPage.cpp : implementation file
//

#include "stdafx.h"
#include "SwordBible.h"
#include "SwordBibleDoc.h"
#include "DevotionalPage.h"
#include "BiblePage.h"
#include ".\devotionalpage.h"
#include "BibleForm.h"


int CDevotionalPage::staticPageCount = 0;  // number of pages created
CSwordBibleFonts CDevotionalPage::font;
// CDevotionalPage dialog

IMPLEMENT_DYNAMIC(CDevotionalPage, CPropertyPage)
CDevotionalPage::CDevotionalPage()
	: CPropertyPage(CDevotionalPage::IDD)
	, m_devotionStartup(FALSE)
{
	
	staticPageCount++;				// increment the instance counter
	version = "";
	pModule = NULL;
   

	
	
}

CDevotionalPage::~CDevotionalPage()
{
	staticPageCount--;
			
}

void CDevotionalPage::DoDataExchange(CDataExchange* pDX)
{
	CPropertyPage::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_DATEPICKER, m_dateCtrl);
	DDX_Check(pDX, IDC_DEVOTION_STARTUP, m_devotionStartup);
	DDX_Control(pDX, IDC_RICHEDIT_DEVOTIONAL, m_devotionalRich);
}


BEGIN_MESSAGE_MAP(CDevotionalPage, CPropertyPage)
	ON_COMMAND(ID_DEVOTIONAL_PRINT,OnPrint)
	ON_COMMAND(ID_DEVOTIONAL_COPY, OnDevotionalCopy)
	ON_COMMAND(ID_DEVOTIONAL_DISPLAY, OnDevotionalDisplay)
	ON_COMMAND(ID_PREVIOUSDATE,OnPreviousDate)
	ON_COMMAND(ID_NEXTDATE,OnNextDate)
	ON_WM_SIZE()
	ON_BN_CLICKED(IDC_DEVOTION_STARTUP, OnBnClickedDevotionStartup)

	ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipNotify)
   ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipNotify)

   ON_NOTIFY(DTN_CLOSEUP, IDC_DATEPICKER, OnCloseDatepicker)
   ON_NOTIFY(EN_MSGFILTER, IDC_RICHEDIT_DEVOTIONAL, OnEnMsgFilter)
END_MESSAGE_MAP()


// CDevotionalPage message handlers

void CDevotionalPage::OnSize(UINT nType, int cx, int cy)
{
	CPropertyPage::OnSize(nType, cx, cy);
	
	CWnd* pWnd = GetDlgItem(IDC_RICHEDIT_DEVOTIONAL);

	if( ::IsWindow(pWnd ->GetSafeHwnd() )) 
	pWnd ->SetWindowPos(NULL,10,40,cx-20,cy-65,SWP_NOZORDER | SWP_NOACTIVATE);

    // position the date and time control
	if(m_dateCtrl.GetSafeHwnd())
		m_dateCtrl.SetWindowPos(NULL, 10, 8, 100 , 20,  SWP_NOZORDER | SWP_NOACTIVATE);


	
	// postion the startup option check box
	CWnd * checkWnd = GetDlgItem(IDC_DEVOTION_STARTUP);

		if(checkWnd->GetSafeHwnd())
        checkWnd->SetWindowPos(NULL, 10, cy - 17, 250,14,
		SWP_NOZORDER | SWP_NOACTIVATE);

	

	

}

BOOL CDevotionalPage::OnInitDialog()
{
	CPropertyPage::OnInitDialog();

	font.location = AFX_DEVOTIONAL;
	font.Load();
	font.ConstructRTF();

		//calculate the width and height of chars
	TEXTMETRIC tm;
	CClientDC dc(GetDlgItem(IDC_RICHEDIT_DEVOTIONAL));
	dc.GetTextMetrics(&tm);
	font.text_cx = tm.tmAveCharWidth;
	font.text_cy = tm.tmHeight + tm.tmExternalLeading;


    // set the check in the startup option check box
	 m_devotionStartup = CSwordBibleDoc::devotion_startup;
	UpdateData(FALSE);

	CTime time;
	m_dateCtrl.GetTime(time);

	// set the key
	CString key;
	int month  = time.GetMonth();
	int day = time.GetDay();

	if(month > 9 && day > 9)
	key.Format("%d.%d",month, day);

	else if(month < 10 && day < 10)
	key.Format("0%d.0%d",month, day);

	else if (month > 9 && day < 10)
	key.Format("%d.0%d",month, day);

	else if (month < 10 && day > 9)
	key.Format("0%d.%d",month, day);

	CSwordBibleDoc::devotionKey = key;


	
	// show devotinal text
	showText();
	
	m_devotionalRich.SetEventMask(ENM_MOUSEEVENTS | ENM_KEYEVENTS | ENM_SCROLLEVENTS);
   
	
	 if (!m_wndFormatBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD
       | WS_VISIBLE | CBRS_TOP |  CBRS_FLYBY | CBRS_TOOLTIPS) ||
       !m_wndFormatBar.LoadToolBar(IDR_DEVOTIONAL_TOOLBAR))
   {
      TRACE0("Failed to create toolbar\n");
      return -1;      // fail to create
   }

	m_wndFormatBar.LoadTCToolBar(24, IDB_TOOLBAR_DEVOTION,IDB_TOOLBAR_DEVOTION,
                              IDB_TOOLBAR_DEVOTION, RGB(255,255,255));


	// Position the control bars using RepositionBars. 
	RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0);

	// Expand the size of the Toolbar window so all controls in it would fit
	

	// Expand the size of the Toolbar window so all controls in it would fit	
	CRect toolBarRect;
	CToolBarCtrl& formatBar = m_wndFormatBar.GetToolBarCtrl();
	formatBar.GetWindowRect(toolBarRect);
	ScreenToClient(toolBarRect);
	toolBarRect.right += 600  ;
	formatBar.MoveWindow(toolBarRect,TRUE);


	
    EnableToolTips();   // enable tool tips for view
 

	// diable the 10 ID_PLACEHOLDER BUTTONS
	for(int n = 0; n < 10; n++)
	formatBar.SendMessage((UINT) TB_ENABLEBUTTON, (WPARAM)(int) ID_PLACEHOLDER1 + n,  (LPARAM) MAKELONG(FALSE, 0) ); 

	
  

    return FALSE;  // return TRUE unless you set the focus to a control
	// EXCEPTION: OCX Property Pages should return FALSE
}



// displays the text in the rich edit box of the devotional
void CDevotionalPage::showText()
{
	
    
	if(!pModule) return;

	pModule->SetKey(CSwordBibleDoc::devotionKey);

	
        CString chapText = font.GetHeaderRTF();
		

		CString titleSize;
		titleSize.Format("\\cf2\\fs%d ", font.text_facesize + 5);
		chapText = chapText +  titleSize + pModule->KeyText() + " (" + pModule->Description() + ")";
		
		// reset the font size
		titleSize.Format("\\fs%d", font.text_facesize);
		chapText = chapText + titleSize + "\\par\\par ";
							
		chapText = chapText  + pModule->RenderText() + "}"; 
							
		chapText.Replace("<a href=\"\">",  "<a href=\"\">\\cf6\\b ");
		chapText.Replace("</a>", "</a>\\cf2\\b0 ");

		m_devotionalRich.SetRTF(chapText);

		m_devotionalRich.SetFocus();

		CreateTips();
}



void CDevotionalPage::CreateTips()
{
	tips.Clear();
	
	FINDTEXTEX ft1, ft2;
	ft1.chrg.cpMin = 0;
	ft1.chrg.cpMax = -1;
	ft1.lpstrText = (LPSTR) "<a href=\"\">";

	ft2.chrg.cpMin = 0;
	ft2.chrg.cpMax = -1;
	ft2.lpstrText = (LPSTR) "</a>";

	int start = 0;
	int end = 0;


	while (true) {

	
	start = m_devotionalRich.FindText(FR_DOWN , &ft1); //find the href start tags  
	end = m_devotionalRich.FindText(FR_DOWN , &ft2); //find the href tags  

	if(start == -1 || end == -1) return;

	CString ref = "";
	m_devotionalRich.GetTextRange(start + 11, end, ref);
	tips.Add(start, end - 11, ref);

	ft1.chrg.cpMin = start;
	ft2.chrg.cpMin = start;

	m_devotionalRich.SetSel(end, end + 4);
	m_devotionalRich.ReplaceSel("");

	m_devotionalRich.SetSel(start,start + 11);
	m_devotionalRich.ReplaceSel("");

	}


}



void CDevotionalPage::OnBnClickedDevotionStartup()
{
	// TODO: Add your control notification handler code here
		// TODO: Add your control notification handler code here
	UpdateData();
	CSwordBibleDoc::devotion_startup = m_devotionStartup;
    AfxGetApp()->WriteProfileInt("Devotional","Startup",m_devotionStartup);
}



BOOL CDevotionalPage::OnToolTipNotify(UINT id, NMHDR *pNMHDR,   LRESULT *pResult)
{
   // need to handle both ANSI and UNICODE versions of the message
   TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
   TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
   CString strTipText;
   UINT nID = pNMHDR->idFrom;
   if (pNMHDR->code == TTN_NEEDTEXTA && (pTTTA->uFlags & TTF_IDISHWND) ||
      pNMHDR->code == TTN_NEEDTEXTW && (pTTTW->uFlags & TTF_IDISHWND))
   {
      // idFrom is actually the HWND of the tool
      nID = ::GetDlgCtrlID((HWND)nID);
   }

   char buf[100];

   if (nID != 0) // will be zero on a separator
   {AfxLoadString(nID,buf,100 ); strTipText.Format("%s",buf);  }

   if (pNMHDR->code == TTN_NEEDTEXTA)
      lstrcpyn(pTTTA->szText, strTipText, sizeof(pTTTA->szText));
   else
      _mbstowcsz(pTTTW->szText, strTipText, sizeof(pTTTW->szText));
   *pResult = 0;

   return TRUE;    // message was handled
}



void CDevotionalPage::OnPrint()
{
		// only the active page should handle the message
  if(  !( ((CPropertySheet*) GetParent())->GetActivePage()   == this) )  
	  return;


    CBibleForm::pControl = (CRichEditCtrl *) GetDlgItem(IDC_RICHEDIT_DEVOTIONAL);
	AfxGetMainWnd()->SendMessageToDescendants(WM_PRINT_CONTROL, (WPARAM) 1 , 0);
  
	
}


void CDevotionalPage::OnCloseDatepicker(NMHDR *pNMHDR, LRESULT *pResult)
{
	
	CTime time;
	m_dateCtrl.GetTime(time);

	// set the key
	CString key;
	int month  = time.GetMonth();
	int day = time.GetDay();

	if(month > 9 && day > 9)
	key.Format("%d.%d",month, day);

	else if(month < 10 && day < 10)
	key.Format("0%d.0%d",month, day);

	else if (month > 9 && day < 10)
	key.Format("%d.0%d",month, day);

	else if (month < 10 && day > 9)
	key.Format("0%d.%d",month, day);

	CSwordBibleDoc::devotionKey = key;

	showText();
	*pResult = 0;
}




void CDevotionalPage::OnDevotionalCopy(void) 
{
	// only the active page should handle the message
  if(  !( ((CPropertySheet*) GetParent())->GetActivePage()   == this) )  
	  return;

  m_devotionalRich.Copy();

}



void CDevotionalPage::OnDevotionalDisplay(void)
{

	// only the active page should handle the message
  if(     ((CPropertySheet*) GetParent())->GetActivePage()   != this) return;

  CColorMgr colordlg(NULL, &font);
	
  if(colordlg.DoModal() == IDOK) {
	  m_devotionalRich.SetBackgroundColor(false, CColorMgr::RTFtoCOLORREF(font.bg_color) );
	  showText();
  }

  

	
}

void CDevotionalPage::OnPreviousDate()
{
	CTime time;
	m_dateCtrl.GetTime(time);          // Get current time
    time = time - CTimeSpan(1,0,0,0);  //  decrease time by 1 day

     m_dateCtrl.SetTime(&time);   // set new time

	 // set the key
	CString key;
	int month  = time.GetMonth();
	int day = time.GetDay();

	if(month > 9 && day > 9)
	key.Format("%d.%d",month, day);

	else if(month < 10 && day < 10)
	key.Format("0%d.0%d",month, day);

	else if (month > 9 && day < 10)
	key.Format("%d.0%d",month, day);

	else if (month < 10 && day > 9)
	key.Format("0%d.%d",month, day);

	CSwordBibleDoc::devotionKey = key;

	  showText();   // update display

}

void CDevotionalPage::OnNextDate()
{

	CTime time;
	m_dateCtrl.GetTime(time);          // Get current time
    time = time + CTimeSpan(1,0,0,0);  //  increase time by 1 day

     m_dateCtrl.SetTime(&time);   // set new time

	 // set the key
	CString key;
	int month  = time.GetMonth();
	int day = time.GetDay();

	if(month > 9 && day > 9)
	key.Format("%d.%d",month, day);

	else if(month < 10 && day < 10)
	key.Format("0%d.0%d",month, day);

	else if (month > 9 && day < 10)
	key.Format("%d.0%d",month, day);

	else if (month < 10 && day > 9)
	key.Format("0%d.%d",month, day);

	CSwordBibleDoc::devotionKey = key;

	 showText();   // update display

}
void CDevotionalPage::OnEnMsgFilter(NMHDR *pNMHDR, LRESULT *pResult)
{
	MSGFILTER *pMsgFilter = reinterpret_cast<MSGFILTER *>(pNMHDR);


	// capture mouse move messages and check if the mouse lies within the rectangle
	// of a scripture reference. If so, show the hand sign
	if(pMsgFilter->msg == WM_MOUSEMOVE )
	{
		CPoint point;                                            
         ::GetCursorPos(&point); //where is the mouse?

		 // change the coordinates of the point from Screen to that of richedit
		m_devotionalRich.ScreenToClient(&point);

		int nchar = m_devotionalRich.CharFromPos(point);

		CString keylist = "";
		int lower = 0, upper = 0;
		if(tips.FromPos(nchar,lower, upper, keylist) == TRUE)
		SetCursor(CBibleSheet::m_hHandCursor);

	}
	
	
	if(pMsgFilter->msg == WM_LBUTTONDOWN)
	{ 
		
		 CPoint point;                                            
         ::GetCursorPos(&point); //where is the mouse?

		 // change the coordinates of the point from Screen to that of richedit
		m_devotionalRich.ScreenToClient(&point);

		int nchar = m_devotionalRich.CharFromPos(point);

		CString keylist = "";
		int lower = 0, upper = 0;
		if(tips.FromPos(nchar,lower, upper, keylist) == FALSE)
		return;

		keylist.Replace(',',';');
		keylist.Replace("and",";");

		 // parse the verse list
	    sword::VerseKey vk;
	    sword::ListKey list = vk.ParseVerseList(keylist, vk , TRUE);
	
	
    // this string contains the RTF for the tooltip that would be displayed
	CString display = font.GetHeaderRTF();

	sword::VerseKey key = "";
	
	if(CSwordBibleDoc::pXrefModuleActive == NULL) return;

	CString fs;
	fs.Format("\\fs%d ",22);
	display += fs;
			
	// iterate through the list of verses and get the corresponsing text for each verse
	for(list= sword::TOP; !list.Error(); list++)
   {	
	  key = (const char*) list;

	 (CSwordBibleDoc::pXrefModuleActive)->setKey(key);

	 display += "\\f2\\cf7\\b " + (CString) CSwordBibleDoc::pXrefModuleActive->KeyText() + "\\b0\\cf8 " 
		+ " " + CSwordBibleDoc::pXrefModuleActive->StripText()  + "\\par";
	  
	}

   display += "}";

    // if l1 and l2 are different, then the link has been split into two lines
         int l1 = m_devotionalRich.LineFromChar(lower);
		 int l2 = m_devotionalRich.LineFromChar(upper);
    		
		 int x1 = m_devotionalRich.PosFromChar(lower).x;
		 int x2 = m_devotionalRich.PosFromChar(upper).x + font.text_cx;
		 int y1 = m_devotionalRich.PosFromChar(lower).y;
		 int y2 = y1 + font.text_cy;

		 // the mouse is over the portion of the link that is in line 1
		 if(l1 != l2 && point.y <= y2) 
		 {
			 CRect r;
			 m_devotionalRich.GetWindowRect(&r);
			 m_devotionalRich.ScreenToClient(&r);
			 x2 = r.right;
		 }

		  // the mouse is over the portion of the link that is in line 2
		 else if(l1 != l2 && point.y > y2)
		 {
			 x1 = 0;
			 y1 = m_devotionalRich.PosFromChar(upper).y;
			 y2 = y1 + font.text_cy;
		 }

	
		 CRect rect(x1,y1, x2, y2);

	
		 CBibleSheet::DisplayReference(display, "Scripture Cross-reference");

	}



	*pResult = 0;
}
